# -*- coding: utf-8 -*-

# @Time    : 2018/12/19 11:19
# @Author  : Chen
# @File    : faceDetect_OpenCV.py
# @Software: PyCharm

import cv2
import os
import PIL.Image as Image
import PIL.ImageDraw as ImageDraw

def detectFaces(image_name): # 人脸检测
    img = cv2.imread(image_name) # 读取图片
    face_cascade = cv2.CascadeClassifier('C:\\Program Files\\Anaconda3\\Library\\etc\\haarcascades\\haarcascade_frontalface_default.xml')
    if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转为灰度图片
    else:
        gray = img # if语句：如果img维度为3，说明不是灰度图，先转化为灰度图gray，如果不为3，也就是2，原图就是灰度图
    faces = face_cascade.detectMultiScale(gray, 1.2, 5)#1.3和5是特征的最小、最大检测窗口，它改变检测结果也会改变
    result = []
    for (x,y,width,height) in faces:
        result.append((x, y, x + width, y + height))
    return result

def saveFaces(image_name): # 截取保存人脸图
    faces = detectFaces(image_name)
    if faces:
        # Image模块：Image.open获取图像句柄，crop剪切图像(剪切的区域就是detectFaces返回的坐标)，save保存。
        savePath = os.path.dirname(image_name) # 获取文件相对路径
        saveName = os.path.basename(image_name).split('.')[0] # 获取文件名（不含格式）
        count = 0
        for (x1,y1,x2,y2) in faces:
            file_name = os.path.join(savePath, saveName + '_face_' + str(count) + os.path.splitext(image_name)[1])
            Image.open(image_name).crop((x1, y1, x2, y2)).save(file_name)
            count += 1
    print('保存成功')

def drawFaces(image_name): # 在原图像上画矩形，框出所有人脸。
    faces = detectFaces(image_name)
    if faces:
        img = Image.open(image_name)
        draw_instance = ImageDraw.Draw(img)
        # 调用Image模块的draw方法，Image.open获取图像句柄，ImageDraw.Draw获取该图像的draw实例，然后调用该draw实例的rectangle方法画矩形(矩形的坐标即detectFaces返回的坐标)，outline是矩形线条颜色(B,G,R)。
        # 注：原始图像如果是灰度图，则去掉outline，因为灰度图没有RGB可言。drawEyes、detectSmiles也一样。
        for (x1, y1, x2, y2) in faces:
            draw_instance.rectangle((x1, y1, x2, y2), outline=(255, 0, 0))
        img.save(os.path.splitext(image_name)[0] + '_drawfaces' + os.path.splitext(image_name)[1])

def detectEyes(image_name): # 眼睛检测
    eye_cascade = cv2.CascadeClassifier('C:\\Program Files\\Anaconda3\\Library\\etc\\haarcascades\\haarcascade_eye.xml')
    faces = detectFaces(image_name)
    img = cv2.imread(image_name)
    if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转为灰度图片
    else:
        gray = img # if语句：如果img维度为3，说明不是灰度图，先转化为灰度图gray，如果不为3，也就是2，原图就是灰度图
    result = []
    for (x1, y1, x2, y2) in faces:
        roi_gray = gray[y1:y2, x1:x2]
        eyes = eye_cascade.detectMultiScale(roi_gray, 1.3, 2)
        for (ex1, ey1, ex2, ey2) in eyes:
            result.append((x1 + ex1, y1 + ey1, x1 + ex1 + ex2, y1 + ey1 + ey2))
    return result

def drawEyes(image_name): # 框出眼睛
    eyes = detectEyes(image_name)
    if eyes:
        img = Image.open(image_name)
        draw_instance = ImageDraw.Draw(img)
        for (x1, y1, x2, y2) in eyes:
            draw_instance.rectangle((x1, y1, x2, y2), outline=(0, 0,255))
        img.save(os.path.splitext(image_name)[0] + '_draweyes' + os.path.splitext(image_name)[1])

def detectSmiles(image_name): # 笑脸检测
    img = cv2.imread(image_name)
    smiles_cascade = cv2.CascadeClassifier('C:\\Program Files\\Anaconda3\\Library\\etc\\haarcascades\\haarcascade_smile.xml')
    if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        gray = img # if语句：如果img维度为3，说明不是灰度图，先转化为灰度图gray，如果不为3，也就是2，原图就是灰度图
    smiles = smiles_cascade.detectMultiScale(gray, 4, 5)
    result = []
    for (x,y,width,height) in smiles:
        result.append((x, y, x + width, y + height))
    return result

def drawSmiles(image_name): # 框出笑脸
    smiles = detectSmiles(image_name)
    if smiles:
        img = Image.open(image_name)
        draw_instance = ImageDraw.Draw(img)
        for (x1, y1, x2, y2) in smiles:
            draw_instance.rectangle((x1, y1, x2, y2), outline=(100, 100,0))
        img.save(os.path.splitext(image_name)[0] + '_drawsmiles' + os.path.splitext(image_name)[1])